import Dictionary from "../map/Dictionary";

interface GraphInterface<T> {
    isDirected: boolean; // 标识图是否有向
    vertices: Array<T>; // 顶点名字
    adjList: Dictionary<T, Array<T>>; // 管理顶点
    addVertex(v: T): void; // 添加顶点
    addEdge(v: T, w: T): void; // 添加关联
    getVertices(): Array<T>; // 获取顶点数组
    getAdjacencyList(): Dictionary<T, Array<T>>; // 获取关联数组
}

export default class Graph<T> implements GraphInterface<T> {
    adjList: Dictionary<T, Array<T>>;
    isDirected: boolean;
    vertices: Array<T>;

    constructor(isDirected: boolean = false) {
        this.adjList = new Dictionary();
        this.isDirected = isDirected;
        this.vertices = [];
    }

    addEdge(v: T, w: T): void {
        if(!this.adjList.get(v)){
            this.addVertex(v);
        }
        if(!this.adjList.get(w)){
            this.addVertex(w);
        }
        if(this.adjList.get(v)?.value?.indexOf(w) === -1){
            this.adjList.get(v)?.value?.push(w);
        }
        if(!this.isDirected){
            if(this.adjList.get(w)?.value?.indexOf(v) === -1){
                this.adjList.get(w)?.value?.push(v);
            }
        }
    }

    addVertex(v: T): void {
        if (this.vertices.indexOf(v) == -1) {
            this.vertices.push(v);
            this.adjList.set(v, []);
        }
    }

    getAdjacencyList(): Dictionary<T, Array<T>> {
        return this.adjList;
    }

    getVertices(): Array<T> {
        return this.vertices;
    }

    toString():string{
        let str = "";
        for (let i = 0; i < this.vertices.length; i++) {
            str += this.vertices[i] + "-->"
            str += this.adjList.get(this.vertices[i])?.toString() || "";
            str += "\n"
        }
        return str;
    }
}
// const graph = new Graph<string>();
// const myVertices = ["A","B","C","D","E","F","G","H","I","J","K"]
// for (let i = 0; i < myVertices.length; i++) {
//     graph.addVertex(myVertices[i]);
// }
//
// graph.addEdge(myVertices[0],myVertices[1])
// graph.addEdge(myVertices[0],myVertices[1])
// graph.addEdge(myVertices[0],myVertices[2])
// graph.addEdge(myVertices[0],myVertices[3])
// graph.addEdge(myVertices[2],myVertices[1])
// graph.addEdge(myVertices[3],myVertices[1])
// graph.addEdge(myVertices[6],myVertices[1])
//
// console.log(graph.toString())
